package main

func main() {

}

/*
适配器模式（Adapter Pattern）又叫作变压器模式，
它的功能是将一个类的接口变成客户端所期望的另一种接口，
从而使原本因接口不匹配而导致无法在一起工作的两个类能够一起工作，属于结构型设计模式。
适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
*/

/*适配器模式中的角色构成如下：

客户端（Client）：首先是客户端，这里的客户端可以理解成通过适配器调用服务的代码程序，代码只需通过接口与适配器交互即可， 无需与具体的适配器类耦合。
客户端接口（Client Interface）：这个接口也可被叫做适配器接口，描述了被适配的类与客户端代码协作时必须遵循的约定。
适配器 （Adapter）： 作为同时与客户端和服务交互的中介类： 它在实现客户端接口的同时封装了服务对象。 适配器接受客户端通过适配器接口发起的调用， 并将其转换为适用于被封装服务对象的调用。
服务（Service）：服务通常是一些第三方功能类库或者是一些遗留系统的功能类，客户端与其不兼容，因此无法直接调用其功能，需要适配器进行转换。

*/

// Target 适配器接口 描述客户端和被适配服务间约定的接口
type Target interface {
	Request() string
}

// Adaptee 是被适配的目标接口
type Adaptee interface {
	SpecificRequest() string
}

type adapteeImpl struct{}

func (ad *adapteeImpl) SpecificRequest() string {
	return "adaptee method"
}

func NewAdaptee() Adaptee {
	return &adapteeImpl{}
}

type adapter struct {
	Adaptee
}

func (a *adapter) Request() string {
	return a.SpecificRequest()
}

func NewAdapter(adaptee Adaptee) Target {
	return &adapter{
		adaptee,
	}
}

/*为什么建议引入依赖库的时候使用适配器模式？
项目使用第三方类库的时候，防止未来有更换同等功能类库的可能，
一般会推荐使用适配器模式对三方类库做一层封装，这样未来需要用同等功能的服务类进行替换时，
实现一个新的适配器包装服务类即可，不需要对已有的客户端代码进行更改。

使用适配器模式，在项目中接入依赖库，这样以后需要替换成其他同等功能的依赖库的时候，不会影响到项目中的通过适配器使用依赖库功能的代码。

适配器与原对象（被适配对象）实现不同的接口，适配器的特点在于兼容，客户端通过适配器的接口完成跟自己不兼容的原对象的访问交互。
代理与原对象（被代理对象）实现相同的接口，代理模式的特点在于隔离和控制，代理直接转发原对象的返回给客户端，但是可以在调用原始对象接口的前后做一些额外的辅助工作，AOP编程的实现也是利用这个原理。

适配器模式的优点是适配器类和原角色类解耦，提高程序的扩展性。在很多业务场景中符合开闭原则。不改变原有接口，却还能使用新接口的功能。
不过适配器的编写过程需要结合业务场景全面考虑，同时也可能会增加系统的复杂性。
*/
